package simple.form.dao;

import simple.form.controller.SysContent;
import simple.form.utils.SafeConvertUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * mysql实现
 * Created by Administrator on 2017/3/6.
 */
public class MysqlExecutor<T> extends SqlExecutor<T>{
    private static MysqlExecutor ourInstance = new MysqlExecutor();

    public static MysqlExecutor getInstance() {
        return ourInstance;
    }

    private MysqlExecutor() {
    }
    @Override
    public T findOne(String sql, Class beanClass) {
        List<T> records = findAll(sql,beanClass);
        if(records!=null&&records.size()==1){
            return records.get(0);
        }else{
            return null;
        }
    }

    @Override
    public T findOne(T bean) {
        List<T> records = findAll(bean);
        if(records!=null&&records.size()==1){
            return records.get(0);
        }else{
            return null;
        }
    }

    @Override
    public List findAll(String sql, Class beanClass) {
        String finalSql = sql;
        if(sql==null||sql.isEmpty()){
            return null;
        }
        if(sql.contains("SELECT")){
            sql = sql.replace("SELECT","");
        }
        if(sql.contains("select")){
            sql = sql.replace("select","");
        }

        if(sql.contains("FROM")){
            sql = sql.replace("from","@");
        }
        if(sql.contains("from")){
            sql = sql.replace("from","@");
        }

        sql = sql.substring(0,sql.indexOf("@")).trim();

        String[] columns=null;

        boolean selectAll = false;
        if(sql.contains(",")){
            selectAll = false;
            columns = sql.split(",");
        }else{
            selectAll = true;
        }

        List<String> findColumn = new ArrayList<>();
        if(columns!=null){
            for(String column:columns){
                if (column.contains(".")){
                    column = column.substring(column.indexOf(".")+1);
                    findColumn.add(column);
                }else{
                    findColumn.add(column);
                }
            }
        }

        Connection conn =null;
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        conn = getCurrentConnection();
        Table table = SysContent.beansMappingTables.get(beanClass.getName());
        Map<String, Class> fields= table.getFields();
        String field;
        Object loadBean = null;
        List<T> records = new ArrayList<>();
        if(selectAll){
            try {
                ps = conn.prepareStatement(finalSql);
                resultSet = ps.executeQuery();
                Iterator iterator =fields.entrySet().iterator();
                while (resultSet.next()){
                    loadBean = newBeanInstance(beanClass);
                    while (iterator.hasNext()){
                        Map.Entry entry = (Map.Entry) iterator.next();
                        field = SafeConvertUtil.toString(entry.getKey());
                        initBean((T) loadBean,resultSet,field,(Class)entry.getValue());

                    }
                    records.add((T)loadBean);

                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                closeresultSet(resultSet);
                closePreparedStatement(ps);
            }
        }else{
            try {
                ps = conn.prepareStatement(finalSql);
                resultSet = ps.executeQuery();
                while (resultSet.next()){
                    loadBean = newBeanInstance(beanClass);
                    Iterator iterator =fields.entrySet().iterator();
                    while (iterator.hasNext()){
                        Map.Entry entry = (Map.Entry)iterator.next();
                        field = SafeConvertUtil.toString(entry.getKey());
                        for(String column:findColumn){
                            if(column.equalsIgnoreCase(field)){
                                initBean((T)loadBean,resultSet,field,(Class)entry.getValue());

                            }
                        }

                    }
                    records.add((T)loadBean);
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                closeresultSet(resultSet);
                closePreparedStatement(ps);
            }
        }
        return  records;
    }

    @Override
    public List findAll(T bean) {
        String sql = createFindSql(bean);
        Class beanClass = bean.getClass();
        T loadBean = null;
        String  beanName = bean.getClass().getName();
        Table table = SysContent.beansMappingTables.get(beanName);
        /*Map<"字段名称","字段类型">*/
        Map<String,Class> fields = table.getFields();
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        List<T> records = new ArrayList<>();
        try {
            conn = getCurrentConnection();
            ps = conn.prepareStatement(sql);
            resultSet = ps.executeQuery();

            while (resultSet.next()){
                loadBean = newBeanInstance(beanClass);
                Iterator iter = fields.entrySet().iterator();
                while (iter.hasNext()){
                    Map.Entry entry = (Map.Entry) iter.next();
                    String field = SafeConvertUtil.toString(entry.getKey());
                    initBean((T)loadBean,resultSet,field,(Class)entry.getValue());

                }
                records.add(loadBean);
            }


        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            closeresultSet(resultSet);
            closePreparedStatement(ps);
        }
        return records;
    }

    @Override
    protected int insert(T bean) {
        String sql = createInsertSql(bean);
        return executeSql(sql);
    }

    @Override
    protected int updateByKey(T bean) {
        String sql = createUpdateByKeySql(bean);
        return executeSql(sql);
    }

    @Override
    protected int delete(T bean) {
        String sql = createDeleteSql(bean);
        return executeSql(sql);
    }
}
